package base

import (
	"fmt"
	"hi-jvm/rtda"
	"hi-jvm/rtda/heap"
)

func InvokeMethod(invokerFrame *rtda.Frame, method *heap.Method) {
	thread := invokerFrame.Thread
	newFrame := thread.NewFrame(method)
	thread.PushFrame(newFrame)

	// 确定参数占用多少位置： 该数量不一定会等于参数个数
	// 1. long，double占用两位
	// 2. 实例方法，在参数列表前添加一个指向实例对象自身的引用
	argSlotCount := int(method.ArgSlotCount)
	if argSlotCount > 0 {
		for i := argSlotCount - 1; i >= 0; i-- {
			slot := invokerFrame.OperandStack.PopSlot()
			newFrame.LocalVars.SetSlot(uint(i), slot)
		}
	}

	// hack!
	if method.IsNative() {
		if method.Name == "registerNatives" {
			thread.PopFrame()
		} else {
			panic(fmt.Sprintf("native method: %v.%v%v\n",
				method.Class.Name, method.Name, method.Descriptor))
		}
	}
}